定期作成されたAMIと関連付けされているSnapshotを指定期間後に削除してみた

定期作成されたAMIと関連付けされているSnapshotを指定期間後に削除してみた

Clock Icon2024.10.24

こんにちは、コンサル部@大阪オフィスのTodaです。

Amazon EC2 をご利用頂く中で定期的なバックアップとしてAMIを取得するケースは多くあると思います。
今回、AMIのバックアップはツールを利用して実施しているが、削除の自動化が出来ておらず大量のAMIが残っていて悩まれているお客様から相談があり解決策の1つとしてLambda処理を利用して自動削除出来る仕組みをご案内させていただきます。

なお、EC2の自動バックアップとAMIの自動削除を合わせて処理する場合は「Amazon Data Lifecycle Manager (DLM)」で処理する案もシンプルに対応出来るためオススメでございます。
DLMを利用したバックアップは 下記参考ページをご参照ください。

https://dev.classmethod.jp/articles/ec2-snapshot-by-amazon-dlm/

実現する事

  • 定期的に生成されるAMIとSnapshotを指定期間後に自動削除する
    • 今回は 90日 経過したAMIの削除を想定します。

試してみる

Lambda関数作成

Python 3.12 にてLambda関数を作成します。
スクリプト内にある「backup_deletion_enable」の変数に 「True」を入れることで実際の削除がおこなわれます。また、事前の検証は当変数に「False」で処理をすることで実行時のログに削除予定のAMIなど把握出来るようにしています。
日数は 90日経過をした物を対象とするようにしています。

プログラムのコードは下記内容になります。

import boto3
from datetime import datetime, timezone, timedelta

#  削除機能を有効化するか (True:有効 / False:無効 削除候補表示のみ)
backup_deletion_enable = False

# 日本時間のタイムゾーンを指定
JST = timezone(timedelta(hours=9))

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    response = ec2.describe_images(Owners=['self'])

    # 現在の日付と90日前の日付を日本時間で取得
    now = datetime.now(JST)
    cutoff_date = now - timedelta(days=90)

    # 削除対象のAMIをフィルタリング
    images = [image for image in response['Images'] 
        if datetime.strptime(image['CreationDate'], '%Y-%m-%dT%H:%M:%S.%fZ').replace(tzinfo=timezone.utc).astimezone(JST) < cutoff_date]

    # AMIとスナップショットを削除
    for image in images:
        image_id = image['ImageId']
        print(f"Delete AMI: {image_id}")
        if backup_deletion_enable:
            ec2.deregister_image(ImageId=image_id)

        # 関連するスナップショットを削除
        for block_device in image['BlockDeviceMappings']:
            if 'Ebs' in block_device:
                snapshot_id = block_device['Ebs']['SnapshotId']
                print(f"Delete Snapshot: {snapshot_id}")
                if backup_deletion_enable:
                    ec2.delete_snapshot(SnapshotId=snapshot_id)

    deleted_images = [image['ImageId'] for image in images]
    return {
        'statusCode': 200,
        'body': f"Deleted AMIs: {deleted_images}"
    }

Lambdaの実行ロールにはAMIとSnapshotの参照・削除に必要な権限が必要になります。
下記サンプルは削除権限を AMIとSnapshot すべてを対象にしております。
必要な場合は、範囲を狭めるなど調整が必要と考えます。

サンプルのポリシーは下記部分を置き換えてご利用ください。

  • [%REGION%] : ご利用のリージョンを指定
  • [%AWS_ID%] : ご利用のAWSアカウント IDを指定
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DeregisterImage"
            ],
            "Resource": [
                "arn:aws:ec2:[%REGION%]:[%AWS_ID%]:image/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeImages"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DeleteSnapshot"
            ],
            "Resource": [
                "arn:aws:ec2:[%REGION%]:[%AWS_ID%]:snapshot/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeSnapshots"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

上記設定後、実行時の引数はデフォルトにて実行する事で削除の動作試験をおこなうことができます。

定期による処理の実行

Lambdaの定期処理は「Amazon EventBridge Scheduler」をご利用頂くのがオススメになります。
下記参考ページをご覧頂き、1日1回定期的にLambdaを実行するスケジュールを設定頂けたらと思います。

https://dev.classmethod.jp/articles/amazon-eventbridge-scheduler-new-way-to-launch-tasks/

さいごに

今回は、定期的に増えるAMIとSnapshotを一定期間にて削除する方法をご案内しました。

会社の規定などでバックアップの保持期間などがあるケースで、期間が過ぎた物は定期的に削除いただく事で
微々たる物ですがコストの削減、バックアップデータの複雑化などを防ぐことが可能です。
少しでもお客様の参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.